from types import FunctionType
from collections import OrderedDict

from django.db.models import Q, Sum
from django.shortcuts import render, HttpResponse
from django.utils.safestring import mark_safe
from django.http import JsonResponse

from web import models
from web.utils.pager import Pagernation
from web.utils.group import Option, get_choice_text, get_search_group_condition


def get_host_state(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text
        method = 'get_%s_display' % field
        value = getattr(obj, field)
        if value == 1:
            state = 'btn btn-warning'
        elif value == 4:
            state = 'btn btn-info'
        else:
            state = 'btn btn-danger'
        field_text = getattr(obj, method)()
        tpl = "<a class='{} btn-xs'>{}</a>".format(state, field_text)

        return mark_safe(tpl)

    return inner


def get_hazard_level(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text
        method = 'get_%s_display' % field
        value = getattr(obj, field)
        if value == 3:
            state = 'btn btn-info'
        elif value == 2:
            state = 'btn btn-warning'
        else:
            state = 'btn btn-danger'
        field_text = getattr(obj, method)()
        tpl = "<a class='{} btn-xs'>{}</a>".format(state, field_text)

        return mark_safe(tpl)

    return inner


def skyeyelog_list(request, pk):
    list_display = [
        get_host_state('攻击结果', 'host_state'),
        'attack_sip',
        'location',
        'alarm_sip',
        'dip',
        'dport',
        'threat_name',
        get_hazard_level('威胁级别', 'hazard_level'),
        'name_type_chain',
        'proto',
        'repeat_count',
        'ioc',
        get_choice_text('攻击维度', 'attack_dimension'),
        'access_time',
    ]
    model_class = models.SkyEyeLog
    # 配置组合搜索
    search_group = [
        Option('hazard_level'),
        Option('super_type'),
        Option('host_state'),
        Option('attack_dimension'),
    ]
    search_group_list = []
    for option_object in search_group:
        search_group_list.append(option_object.get_queryset_or_tuple(request, model_class))
    # 获取组合搜索条件
    conn = get_search_group_condition(search_group, request)

    # 获取搜索条件
    search_list = [
        'attack_sip__contains',
        'location__contains',
        'dip__contains',
        'name_type_chain__contains',
        'proto__contains',
        'ioc__contains'
    ]
    keyword = request.GET.get("keyword", "").strip()
    con = Q()
    con.connector = "OR"
    if keyword:
        for item in search_list:
            con.children.append((item, keyword))

    obj = models.SkyEye.objects.filter(id=pk).first()
    data_time = obj.create_datetime
    queryset = models.SkyEyeLog.objects.filter(con).filter(**conn). \
        filter(create_datetime__year=data_time.year,
               create_datetime__month=data_time.month,
               create_datetime__day=data_time.day).order_by('attack_sip')

    pager = Pagernation(request, queryset)
    # 1.处理表头
    header_list = []
    if list_display:
        for key_or_func in list_display:
            if isinstance(key_or_func, FunctionType):
                header_list.append(key_or_func(None, True))
            else:
                verbose_name = model_class._meta.get_field(key_or_func).verbose_name
                header_list.append(verbose_name)
    else:
        header_list.append(model_class._meta.model_name)
    # 2.处理表格内容
    data_list = queryset[pager.start:pager.end]
    body_list = []
    for row in data_list:
        tr_list = []
        if list_display:
            for key_or_func in list_display:
                if isinstance(key_or_func, FunctionType):
                    tr_list.append(key_or_func(row, False))
                else:
                    tr_list.append('' if getattr(row, key_or_func) == None else getattr(row, key_or_func))
        else:
            tr_list.append(row)
        body_list.append(tr_list)

    pager = Pagernation(request, queryset)
    context = {
        'body_list': body_list,
        'header_list': header_list,
        'pager': pager,
        'keyword': keyword,
        'search_group_row_list': search_group_list
    }
    return render(request, 'list.html', context)


def statistics_attackip(request):
    pk = request.GET.get('id')
    obj = models.SkyEye.objects.filter(id=pk).first()
    date_time = obj.create_datetime
    queryset = models.SkyEyeLog.objects.filter(create_datetime__year=date_time.year,
                                               create_datetime__month=date_time.month,
                                               create_datetime__day=date_time.day). \
        values('attack_sip').annotate(ct=Sum('repeat_count')).order_by("-ct")
    all_attackip_dict = OrderedDict()
    for item in queryset:
        all_attackip_dict[item['attack_sip']] = {
            'name': item['attack_sip'],
            'hazard_level': {item[0]: 0 for item in models.SkyEyeLog.hazard_level_choices}
        }
    attack_log = models.SkyEyeLog.objects.filter(create_datetime__year=date_time.year,
                                                create_datetime__month=date_time.month,
                                                create_datetime__day=date_time.day)

    for item in attack_log:
        all_attackip_dict[item.attack_sip]['hazard_level'][item.hazard_level] += 1

    categories = [data['name'] for data in all_attackip_dict.values()]

    data_result_dict = OrderedDict()
    for item in models.SangforFwAttackLog.level_choices:
        data_result_dict[item[0]] = {'name': item[1], "data": []}
    for key, text in models.SangforFwAttackLog.level_choices:
        for row in all_attackip_dict.values():
            count = row['level'][key]
            data_result_dict[key]['data'].append(count)
    context = {
        'status': True,
        'data': {
            'categories': categories,
            'series': list(data_result_dict.values())
        }
    }

    return JsonResponse(context)
